﻿using FPSO.Models.Constant;
using FPSO.Models.Domain;
using FPSO.Models.ViewModel.Controls;
using FPSO.ViewModel.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using static FPSO.Models.Constant.TankConstant;

namespace FPSO.Services.Impl
{
    /// <summary>
    /// 模拟的液货舱 服务实现
    /// </summary>
    public class ImitateOilBallastServiceImpl : IOilBallastService
    {
        private UCOilBallastViewModel viewModel;
        private List<TankViewModel> wbtTankViewList;
        private List<TankOilViewModel> oilTankViewList;
        private List<ValveViewModel> valveViewList;
        private ITankTaskService taskService;

        public ImitateOilBallastServiceImpl(UCOilBallastViewModel viewModel, ITankTaskService taskService)
        {
            this.viewModel = viewModel;
            this.taskService = taskService;
            this.wbtTankViewList = new List<TankViewModel>();
            this.oilTankViewList = new List<TankOilViewModel>();
            this.valveViewList = new List<ValveViewModel>();

            PropertyInfo[] propertys = typeof(UCOilBallastViewModel).GetProperties();
            foreach(PropertyInfo p in propertys)
            {
                object propVal = p.GetValue(viewModel);

                if (propVal is TankViewModel t)
                {
                    wbtTankViewList.Add(t);
                }
                else if (propVal is TankOilViewModel o)
                {
                    oilTankViewList.Add(o);
                }
                else if (propVal is ValveViewModel v)
                {
                    valveViewList.Add(v);
                }
            }
        }

        public void ReflushData(DateTime currentTime)
        {
            HashSet<string> openValveSet = new HashSet<string>();
            List<TankTask> task1List = taskService.GetWaitAndExecingTaskList(TaskQueueConstant.LOAD_TASK_1_ID);
            List<TankTask> task2List = taskService.GetWaitAndExecingTaskList(TaskQueueConstant.LOAD_TASK_2_ID);
            task1List.AddRange(task2List);
            
            foreach(TankTask task in task1List)
            {
                if (currentTime < task.PlanStartTime || currentTime > task.PlanEndTime)
                    continue;

                //油舱
                if (TankConstant.TankIdIsCOT(task.TankId))
                {
                    ImitateOilTank(task, currentTime, openValveSet);
                }
                else
                {
                    ImitateWBTTank(task, currentTime, openValveSet);
                }
            }

			foreach (ValveViewModel valve in valveViewList)
			{
				double a = 0;
				//valve.Active = openValveSet.Contains(valve.ValveId);
			}
		}

        public void ReflushData(ManualCalcResult calcResult)
        {

        }


        private void ImitateOilTank(TankTask task, DateTime currentTime, HashSet<string> valveSet)
        {
            TankOilViewModel tankModel = oilTankViewList.Where(t => t.TankId == task.TankId).FirstOrDefault();
            if (tankModel != null)
            {
                double taskHours = (task.PlanEndTime - task.PlanStartTime).TotalHours;
                double curHours = (currentTime - task.PlanStartTime).TotalHours;
                tankModel.Rate = task.PipeSpeed;
                tankModel.Volume = tankModel.TotalVolume * task.TargetVolm * 0.01 * curHours / taskHours;
            }
        }

        private void ImitateWBTTank(TankTask task, DateTime currentTime, HashSet<string> valveSet)
        {
            if (task.TaskType == TaskTypeConstant.LOAD_ID)
            {
                List<ConstantTaskDevice> valveList = TankConstant.GetTaskRelationValve(task.TankId, "", TaskTypeConstant.UNBALLAST_ID);
                if (valveList != null)
                {
                    foreach (ConstantTaskDevice valve in valveList)
                    {
                        valveSet.Add(valve.DeviceId);
                    }
                }

                TankViewModel tankModel = wbtTankViewList.Where(t => t.TankId == task.TankId).FirstOrDefault();
                if (tankModel != null)
                {
                    double taskHours = (task.PlanEndTime - task.PlanStartTime).TotalHours; //TaskUtils.CalcTaskUseHours(task);
                    double curHours = (currentTime - task.ExecStartTime).TotalHours;
                    tankModel.Rate = task.PipeSpeed;
                    tankModel.Volume = tankModel.TotalVolume * task.TargetVolm * 0.01 * curHours / taskHours;
                }
            }
            if (task.TaskType == TaskTypeConstant.UNLOAD_ID)
            {
                List<ConstantTaskDevice> valveList = TankConstant.GetTaskRelationValve("", task.TankId, TaskTypeConstant.BALLAST_ID);
                if (valveList != null)
                {
                    foreach (ConstantTaskDevice valve in valveList)
                    {
                        valveSet.Add(valve.DeviceId);
                    }
                }

                TankViewModel tankModel = wbtTankViewList.Where(t => t.TankId == task.TankId).FirstOrDefault();
                if (tankModel != null)
                {
                    double taskHours = (task.PlanEndTime - task.PlanStartTime).TotalHours; //TaskUtils.CalcTaskUseHours(task);
                    double curHours = (currentTime - task.ExecStartTime).TotalHours;
                    tankModel.Rate = task.PipeSpeed;
                    tankModel.Volume = tankModel.TotalVolume * task.TargetVolm * 0.01 * curHours / taskHours;
                }
            }
        }
    }
}
